<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="T76hK" id="T76hK"><span data-lake-id="u6526a963" id="u6526a963">典型回答</span></h1>
  <p data-lake-id="u9d76ea77" id="u9d76ea77"><br></p>
  <p data-lake-id="u1976bd67" id="u1976bd67"><span data-lake-id="ua04963b1" id="ua04963b1">所谓自适应限流，就是限流器结合服务器实例的Load、CPU、内存、接口的RT、QP、并发线程数等指标，进行的一种自适应的流控策略。即通过监控这些指标的变化，来动态的调整限流，来达到保证系统稳定性的目的。</span></p>
  <p data-lake-id="uc1edb051" id="uc1edb051"><span data-lake-id="u9626ba19" id="u9626ba19">​</span><br></p>
  <p data-lake-id="u4dffd298" id="u4dffd298"><span data-lake-id="u5b0b9a03" id="u5b0b9a03">这种思想也有很多其他的应用，比如自适应扩容，也是根据机器的Load，CPU等情况，进行动态的扩容等。</span></p>
  <p data-lake-id="ua6d7e721" id="ua6d7e721"><span data-lake-id="u443bdf56" id="u443bdf56">​</span><br></p>
  <p data-lake-id="u8dbf8eb5" id="u8dbf8eb5"><span data-lake-id="u13b4ef05" id="u13b4ef05">其实主要就是要给系统定义一个基线，或者水位，一旦这些指标达到了水位之上，比如CPU利用率超过60%，那么就开启自适应限流，通过限流的方式来保护系统不被打垮。</span></p>
  <p data-lake-id="u4f2fda34" id="u4f2fda34"><span data-lake-id="u6d6732af" id="u6d6732af">​</span><br></p>
  <p data-lake-id="u951b322c" id="u951b322c"><span data-lake-id="u12d59d4c" id="u12d59d4c">注明的Sentinal限流框架就支持自适应限流，目前他支持以下的阈值类型：</span></p>
  <ul list="ucf8c1d62">
   <li fid="u5ff2d728" data-lake-id="ue4812ae3" id="ue4812ae3" data-lake-index-type="true"><span data-lake-id="u0d7ccee7" id="u0d7ccee7">Load</span><span data-lake-id="u2de12eac" id="u2de12eac">（仅对 Linux/Unix-like 机器生效）：当系统 load1 超过阈值，且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的</span><span data-lake-id="udfe4a8aa" id="udfe4a8aa"> </span><span data-lake-id="u1ceccd9d" id="u1ceccd9d">maxQps * minRt</span><span data-lake-id="u0613918a" id="u0613918a"> </span><span data-lake-id="ud757f5b5" id="ud757f5b5">计算得出。设定参考值一般是</span><span data-lake-id="u8a972f3c" id="u8a972f3c"> </span><span data-lake-id="ua73da245" id="ua73da245">CPU cores * 2.5</span><span data-lake-id="uf3745618" id="uf3745618">。</span></li>
   <li fid="u5ff2d728" data-lake-id="u2976f4fe" id="u2976f4fe" data-lake-index-type="true"><span data-lake-id="u849d0134" id="u849d0134">CPU usage</span><span data-lake-id="ua0fb67ff" id="ua0fb67ff">（1.5.0+ 版本）：当系统 CPU 使用率超过阈值即触发系统保护（取值范围 0.0-1.0）。</span></li>
   <li fid="u5ff2d728" data-lake-id="u16fad3e9" id="u16fad3e9" data-lake-index-type="true"><span data-lake-id="u59d5ec9c" id="u59d5ec9c">RT</span><span data-lake-id="u428ab849" id="u428ab849">：当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护，单位是毫秒。</span></li>
   <li fid="u5ff2d728" data-lake-id="u9c88776e" id="u9c88776e" data-lake-index-type="true"><span data-lake-id="ub67dc09e" id="ub67dc09e">线程数</span><span data-lake-id="uf96c22fa" id="uf96c22fa">：当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。</span></li>
   <li fid="u5ff2d728" data-lake-id="ub4f6ecca" id="ub4f6ecca" data-lake-index-type="true"><span data-lake-id="uea6c42e4" id="uea6c42e4">入口 QPS：当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。</span></li>
  </ul>
  <p data-lake-id="uffdeed89" id="uffdeed89"><span data-lake-id="u1207b68d" id="u1207b68d">​</span><br></p>
  <p data-lake-id="uc1852bd9" id="uc1852bd9"><span data-lake-id="u74c446b1" id="u74c446b1">以下是Sentinal给的一个自适应限流的示例，供参考：</span></p>
  <p data-lake-id="u9ed3f7ea" id="u9ed3f7ea"><span data-lake-id="ua0a19b77" id="ua0a19b77">​</span><br></p>
  <pre lang="java"><code>
/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.demo.system;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.alibaba.csp.sentinel.util.TimeUtil;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;

/**
 * @author jialiang.linjl
 */
public class SystemGuardDemo {

    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();

    private static volatile boolean stop = false;
    private static final int threadCount = 100;

    private static int seconds = 60 + 40;

    public static void main(String[] args) throws Exception {

        tick();
        initSystemRule();

        for (int i = 0; i &lt; threadCount; i++) {
            Thread entryThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        Entry entry = null;
                        try {
                            entry = SphU.entry("methodA", EntryType.IN);
                            pass.incrementAndGet();
                            try {
                                TimeUnit.MILLISECONDS.sleep(20);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        } catch (BlockException e1) {
                            block.incrementAndGet();
                            try {
                                TimeUnit.MILLISECONDS.sleep(20);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        } catch (Exception e2) {
                            // biz exception
                        } finally {
                            total.incrementAndGet();
                            if (entry != null) {
                                entry.exit();
                            }
                        }
                    }
                }

            });
            entryThread.setName("working-thread");
            entryThread.start();
        }
    }

    private static void initSystemRule() {
        SystemRule rule = new SystemRule();
        // max load is 3
        rule.setHighestSystemLoad(3.0);
        // max cpu usage is 60%
        rule.setHighestCpuUsage(0.6);
        // max avg rt of all request is 10 ms
        rule.setAvgRt(10);
        // max total qps is 20
        rule.setQps(20);
        // max parallel working thread is 10
        rule.setMaxThread(10);

        SystemRuleManager.loadRules(Collections.singletonList(rule));
    }

    private static void tick() {
        Thread timer = new Thread(new TimerTask());
        timer.setName("sentinel-timer-task");
        timer.start();
    }

    static class TimerTask implements Runnable {
        @Override
        public void run() {
            System.out.println("begin to statistic!!!");
            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;

                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;

                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;

                System.out.println(seconds + ", " + TimeUtil.currentTimeMillis() + ", total:"
                    + oneSecondTotal + ", pass:"
                    + oneSecondPass + ", block:" + oneSecondBlock);
                if (seconds-- &lt;= 0) {
                    stop = true;
                }
            }
            System.exit(0);
        }
    }
}
</code></pre>
 </body>
</html>